package hydrap2p.proxy.manager;

import hydrap2p.ServiceLocation;
import hydrap2p.helper.ServiceConnector;
import hydrap2p.helper.ThriftServerThread;
import hydrap2p.helper.Utility;
import hydrap2p.servicemanager.ServiceManager;
import hydrap2p.modulemanager.ModuleControl;
import hydrap2p.servicemanager.NameTaken;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.BindException;

public class Main {

	public static int InstanceID;
	private static Server server;
	public static int ManagerPort;
	public static ThriftServerThread moduleController;
	
	public static void main(String[] args)
	{
		InstanceID=(int) (Math.random()*Integer.MAX_VALUE);
		int managerport;
		try {
			managerport = Utility.getManagerPort();
		} catch (NumberFormatException e) {
			// Could not parse config
			System.err.println("Failed to parse config to find Manager's port");
			return;
		} catch (FileNotFoundException e) {
			// Could not find config
			System.err.println("Failed to locate config to find Manager's port");
			return;
		}

		Configuration config;
		try {
			config = new Configuration();
		} catch (NumberFormatException e1) {
			// Could not parse config
			System.err.println("Failed to parse tunnel configuration");
			return;
		} catch (FileNotFoundException e1) {
			// Could not find config
			System.err.println("Failed to locate tunnel configuration: "+e1.getMessage());
			return;
		}
		
		int tunnelport=config.getListenPort();
		if (tunnelport!=-1)
		{
			try {
				ManagerConnectionManager.create(tunnelport);
			} catch (IOException e) {
				// Failed to start listening
				System.err.println("Could not start tunnel at port "+tunnelport);
				return;
			}				// code to handle connections between other managerproxies
		}
		else
			ManagerConnectionManager.create();

		ServiceManager.Iface manager=ServiceConnector.getServiceManager();
		try {
			if (manager==null)		// no real manager found locally
			{
				server=new Server(managerport);
				server.start();
			}
		} catch (IOException e) {
			// Could not start listening like a manager, weird
			System.err.println("Could not start listening as a Manager");
			e.printStackTrace();
			return;
		}
		
		if (manager!=null)
		{
			try {
				moduleController=new ThriftServerThread(new ModuleControl.Processor(new ModuleControlListener()), "ProxyManagerCTL");
				moduleController.start();
			} catch (BindException e) {
				// Shouldn't happen with ephemeral ports
				System.err.println("Could not start Module Control listening");
				System.exit(0);
			} catch (IOException e) {	
				// Could not connect to Manager
				System.err.println("Could not communicate with Manager to register Module Control");
				System.exit(0);
			} catch (NameTaken e) {
				// Could not register name
				System.err.println("It appears that a Module Control port is already running");
				System.exit(0);
			}

			ManagerPort=managerport;
			ManagerConnectionManager.getInstance().sendManagerLocation(new ServiceLocation("127.0.0.1",managerport));
		}

		ManagerConnectionManager.getInstance().startConnections(config);
	}
}
